chore: add support for react-native@0.87.0-rc.3 - #4375
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates react-native-screens to build and type-check against react-native@0.87.0-rc.1, including related dependency/tooling bumps and several type-level adjustments required by upstream React Native and Android Gradle Plugin changes.
Changes:
- Update JS/TS types and component implementations to align with RN 0.87 type exports and stricter TS settings (e.g.,
ViewInstance, removed RN exports,exactOptionalPropertyTypes). - Adjust Android Gradle integration for AGP 9 built-in Kotlin behavior and update example Android tooling (Gradle, SDK, Kotlin).
- Initialize default Fabric
_propsin several iOS component views to match RN 0.87 expectations.
Reviewed changes
Copilot reviewed 28 out of 33 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Switch TS module resolution to bundler and adjust path mappings for the library. |
| src/types.tsx | Update public types for RN 0.87 (e.g., ViewInstance) and add local TextInputFocusEventData compatibility type. |
| src/private/hooks/useRenderDebugInfo.tsx | Replace removed/renamed RN types (ReactNativeElement → HostInstance). |
| src/gesture-handler/fabricUtils.ts | Update ref/instance typing to RN 0.87’s ViewInstance. |
| src/fabric/SearchBarNativeComponent.ts | Update native commands typing to newer React ref helper types. |
| src/components/tabs/host/TabsHost.android.tsx | Avoid passing { direction: undefined } in styles under stricter typing. |
| src/components/SearchBar.tsx | Refactor SearchBar ref/commands wiring to match RN 0.87 typing changes. |
| src/components/ScreenStackItem.tsx | Update forwarded ref typing and tighten optional style handling. |
| src/components/ScreenStackHeaderConfig.tsx | Adjust non-iOS alignItems to explicit Yoga default (stretch). |
| src/components/Screen.web.tsx | Attempt to pass ref through to inner web <View/>. |
| src/components/Screen.tsx | Update ref typing and add cast workaround for zIndex: undefined under exactOptionalPropertyTypes. |
| src/components/gamma/stack/host/StackHost.types.ts | Update host ref type from ReactNativeElement to HostInstance. |
| src/components/gamma/stack/host/StackHost.tsx | Normalize ref passed to native component (undefined → null). |
| src/components/gamma/stack/header/ios/StackHeaderItem.ios.tsx | Guard Image.resolveAssetSource returning falsy. |
| package.json | Bump RN toolchain/dev deps to 0.87.0-rc.1 and TypeScript to ^6.0.3. |
| ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm | Set default Fabric _props in initializer. |
| ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm | Set default Fabric _props in initializer. |
| ios/RNSScreenFooter.mm | Set default Fabric _props in initializer. |
| ios/RNSScreenContentWrapper.mm | Add initWithFrame to set default Fabric _props. |
| ios/gamma/stack/host/RNSStackHostComponentView.mm | Set default Fabric _props in initializer. |
| ios/gamma/modals/form-sheet/RNSFormSheetContentWrapperComponentView.mm | Add initWithFrame to set default Fabric _props. |
| FabricExample/yarn.lock | Update example lockfile for RN 0.87 toolchain and dependency graph changes. |
| FabricExample/tsconfig.json | Update example TS types list. |
| FabricExample/package.json | Bump example app RN + toolchain deps to 0.87.0-rc.1 and TS ^6.0.3. |
| FabricExample/ios/Podfile.lock | Update CocoaPods lockfile for RN 0.87.0-rc.1 pods/layout. |
| FabricExample/android/gradlew | Update gradlew template link reference. |
| FabricExample/android/gradle/wrapper/gradle-wrapper.properties | Bump Gradle distribution to 9.4.1. |
| FabricExample/android/gradle.properties | Add AGP 9 opt-outs for built-in Kotlin and new DSL. |
| FabricExample/android/build.gradle | Bump compile/build tools and Kotlin versions. |
| FabricExample/android/app/build.gradle | Switch to proguard-android-optimize.txt. |
| android/build.gradle | Conditionally apply Kotlin plugin based on AGP 9 built-in Kotlin; add kotlin source dir configuration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
1cc1087 to
2c32054
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 63 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
src/legacy/components/SearchBar.tsx:28
props.refis now being consumed directly (React 19 ref-as-prop), butSearchBarProps['ref']is typed asReact.RefObject<...>only. That prevents callback refs ((instance) => {}) from type-checking, even thoughuseImperativeHandlesupports them. Consider widening the public prop type toReact.Ref<SearchBarCommands | null>(or equivalent) so both object and callback refs work.
src/legacy/components/helpers/prepareHeaderBarButtonItems.ts:66prepareHeaderBarButtonItemsis exported but currently has an inferred return type and optional-chains an argument that’s already typed as a non-null array. Adding an explicit return type and using.mapdirectly helps keep the emitted.d.tssurface stable and avoids leaking implementation-only types into declarations.
kligarski
left a comment
There was a problem hiding this comment.
Looks good but I left a few minor comments that we should look at before proceeding.
There was a problem hiding this comment.
Don't we also need to apply the same update to library-level gradle-wrapper.properties?
There was a problem hiding this comment.
I decided not to bump because it hasn't been bumped in many previous RN upgrades; tbh, not sure whether we should consider bumping that, but I think this might be another topic - the Kotlin version for the library is still set to 1.8.0 while on the example app's side it is 2+. I'd leave it as-is for now.
kligarski
left a comment
There was a problem hiding this comment.
Looks good. I haven't checked the runtime after the changes.
Upgrade based on the RN upgrade helper: https://react-native-community.github.io/upgrade-helper/?from=0.86.0&to=0.87.0-rc.3 Closes: software-mansion/react-native-screens-labs#1666 - Bumped RN.packages to `0.87.0-rc.3` and TypeScript to TS6 - Bumped AGP on Android to 9 - Bumped `react-native-safe-area-context` to 5.8.0 - https://github.com/AppAndFlow/react-native-safe-area-context/releases/tag/v5.8.0 - the PR released in this version is fixing the build error for symbols that were removed in RN 0.87. - In RN 0.87's generated types, `View` is a function component, so `React.Ref<View>` / `useRef<View>` no longer describe a host instance. All ref sites (e.g., `Screen`, `ScreenStackItem`, `ScreenStackHeaderConfig`) now use the public `ViewInstance` type. - RN 0.87's real types live under the `types_generated/` (treated as non-public) path, so any *inferred* exported type referencing them fails `.d.ts` emit during `npm pack` (`bob build`). Fixes: - `as HostComponent<NativeProps>` on ~30 `codegenNativeComponent` default exports (`HostComponent` is publicly exported; other libs are following that pattern with an explicit cast: https://github.com/software-mansion/react-native-reanimated/blame/4.5.3/packages/react-native-reanimated/src/specs/SharedTransitionBoundaryNativeComponent.ts#L9-L12 - Nominal instance interfaces for `forwardRef` components (`export interface ScreenInstance extends ViewInstance {}`, same for `ScreenStackHeaderConfigInstance`) - inference stops at a nominal interface, so the fix propagates without further annotations (was resolving to `ReactNativeElement`, which is a non-public type from RN) - Exported `TransitionProgressContextBody` and used it as the explicit return type of `useTransitionProgress`. - Set `rootDir: "./src"` in `tsconfig.build.json` - `moduleResolution: "bundler"`, dropped `baseUrl`.** `bundler` resolution is required to resolve RN 0.87's `exports`-based type entry points; `baseUrl` is deprecated in TS 6 and the `paths` mappings work relative to the config without it. For more context, see: microsoft/TypeScript#62508 - Restored the removed `TextInputFocusEventData`. RN changed the exported type to `TextInputFocusEvent` (now the full `NativeSyntheticEvent`). A local backward-compat interface is introduced. - Migrated from `forwardRef` to React 19 ref-as-prop - Retyped the internal ref against the native host instance (`React.ComponentRef<typeof SearchBarNativeComponent>`) instead of the previous double-casted `NativeSearchBar` wrapper. - Added missing `_props` default initializers to Fabric component views (e.g., `RNSScreenContentWrapper`). `RCTViewComponentView`'s `updateProps:oldProps:` asserts in debug builds that every subclass initializes `_props` with its own concrete default props in its initializer, starting from 0.87. - AGP 9 has built-in Kotlin support. - AGP 9 compiles Kotlin itself by default, and additionally applying `kotlin-android` plugin fails the build - so the plugin is now applied only when built-in Kotlin is inactive (AGP < 9, or the consumer opted out via `android.builtInKotlin=false`). - Registered `src/fabric/java` in the Kotlin source set so the Fabric sources compile under built-in Kotlin. N/A - `yarn check-types` - passed - `npm pack` - passed - codegen was verified - `FabricExample` - built and run on iOS and Android. - Checked the compatibility with the lowest supported RN version (0.84) Action items yet to be covered: - test it with SwiftPM - full testing coverage of the most important components on (0.84, 0.87) x (Android, iOS) x (Debug, Release) combos - more FabricExample testing - both Debug and Release - consider adding some commit-level check for detecting issues related to non-public types and TS inference. - [ ] Included code example that can be used to test this change. - [ ] For visual changes, included screenshots / GIFs / recordings documenting the change. - [ ] For API changes, updated relevant public types. - [ ] Ensured that CI passes --------- Co-authored-by: Hur Ali <hurali97@gmail.com> (cherry picked from commit 7708a4a) Co-authored-by: Hur Ali <hurali97@gmail.com>
Description
Upgrade based on the RN upgrade helper: https://react-native-community.github.io/upgrade-helper/?from=0.86.0&to=0.87.0-rc.3
Closes: https://github.com/software-mansion/react-native-screens-labs/issues/1666
Changes
Baseline
0.87.0-rc.3and TypeScript to TS6react-native-safe-area-contextto 5.8.0 - https://github.com/AppAndFlow/react-native-safe-area-context/releases/tag/v5.8.0 - the PR released in this version is fixing the build error for symbols that were removed in RN 0.87.TypeScript - RN 0.87 strict TS API + TS 6 support
Viewis a function component, soReact.Ref<View>/useRef<View>no longer describe a host instance. All ref sites (e.g.,Screen,ScreenStackItem,ScreenStackHeaderConfig) now use the publicViewInstancetype.types_generated/(treated as non-public) path, so any inferred exported type referencing them fails.d.tsemit duringnpm pack(bob build). Fixes:as HostComponent<NativeProps>on ~30codegenNativeComponentdefault exports (HostComponentis publicly exported; other libs are following that pattern with an explicit cast: https://github.com/software-mansion/react-native-reanimated/blame/4.5.3/packages/react-native-reanimated/src/specs/SharedTransitionBoundaryNativeComponent.ts#L9-L12forwardRefcomponents (export interface ScreenInstance extends ViewInstance {}, same forScreenStackHeaderConfigInstance) - inference stops at a nominal interface, so the fix propagates without further annotations (was resolving toReactNativeElement, which is a non-public type from RN)TransitionProgressContextBodyand used it as the explicit return type ofuseTransitionProgress.rootDir: "./src"intsconfig.build.jsonmoduleResolution: "bundler", droppedbaseUrl.**bundlerresolution is required to resolve RN 0.87'sexports-based type entry points;baseUrlis deprecated in TS 6 and thepathsmappings work relative to the config without it. For more context, see: 6.0 Migration Guide microsoft/TypeScript#62508TextInputFocusEventData. RN changed the exported type toTextInputFocusEvent(now the fullNativeSyntheticEvent). A local backward-compat interface is introduced.SearchBar
forwardRefto React 19 ref-as-propReact.ComponentRef<typeof SearchBarNativeComponent>) instead of the previous double-castedNativeSearchBarwrapper.iOS
_propsdefault initializers to Fabric component views (e.g.,RNSScreenContentWrapper).RCTViewComponentView'supdateProps:oldProps:asserts in debug builds that every subclass initializes_propswith its own concrete default props in its initializer, starting from 0.87.Android
kotlin-androidplugin fails the build - so the plugin is now applied only when built-in Kotlin is inactive (AGP < 9, or the consumer opted out viaandroid.builtInKotlin=false).src/fabric/javain the Kotlin source set so the Fabric sources compile under built-in Kotlin.Before & after - visual documentation
N/A
Test plan
yarn check-types- passednpm pack- passedFabricExample- built and run on iOS and Android.Action items yet to be covered:
Checklist